use druid::{
    AppLauncher, Data, Lens, LocalizedString, PlatformError, Widget, WidgetExt, WindowDesc,
};
use druid_widget_nursery::{Tree, TreeNode};
use keepasst_core::{camphor::Camphor, core::group::Group};
use std::convert::From;
use std::fmt;
use std::rc::Rc;

#[derive(Clone)]
pub struct AppState {
    camphor: Camphor
}

impl AppState {

    pub const group: AppStateGroup = AppStateGroup;

    pub fn new() -> Self {
        AppState {
            camphor: Camphor::new().unwrap(),
        }
    }
}

impl Data for AppState {
    fn same(&self, other: &Self) -> bool {
        true
    }
}

pub struct AppStateGroup;

impl Lens<AppState, Rc<Group>> for AppStateGroup {
    fn with<R, F: FnOnce(&Rc<Group>) -> R>(&self, data: &AppState, f: F) -> R {
        let g = data.camphor.group();
        f(&g)
    }

    fn with_mut<R, F: FnOnce(&mut Rc<Group>) -> R>(&self, data: &mut AppState, f: F) -> R {
        f(&mut data.camphor.group())
    }
}

#[derive(Clone, Lens, Debug, PartialEq)]
pub struct Taxonomy {
    pub name: String,
    pub children: Vec<Taxonomy>,
}

/// We use Taxonomy as a tree node, implementing both the Data and TreeNode traits.
impl Taxonomy {
    pub fn new(name: String) -> Self {
        Taxonomy {
            name: name,
            children: Vec::new(),
        }
    }
    pub fn new1(name: &str) -> Self {
        Taxonomy {
            name: name.to_string(),
            children: Vec::new(),
        }
    }

    pub fn add_child(mut self, child: Self) -> Self {
        self.children.push(child);
        self
    }
}

impl Default for Taxonomy {
    fn default() -> Self {
        Self::new("Life".to_string())
    }
}

impl Data for Taxonomy {
    fn same(&self, other: &Self) -> bool {
        self.name.same(&other.name)
            && self.children.len() == other.children.len()
            && self
                .children
                .iter()
                .zip(other.children.iter())
                .all(|(a, b)| a.same(b))
    }
}

impl TreeNode for Taxonomy {
    fn children_count(&self) -> usize {
        self.children.len()
    }

    fn get_child(&self, index: usize) -> &Taxonomy {
        &self.children[index]
    }

    fn get_child_mut(&mut self, index: usize) -> &mut Taxonomy {
        &mut self.children[index]
    }
}

impl fmt::Display for Taxonomy {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.write_str(&self.name)
    }
}

impl From<Rc<Group>> for Taxonomy {
    fn from(g: Rc<Group>) -> Self {
        let mut taxonomy = Taxonomy::new(g.name().clone());

        fn rec_f (mut taxs: Taxonomy, taxg: Rc<Group>) -> Taxonomy {
            for elem in &*taxg.children() {
                let mut c_taxs = Taxonomy::new(elem.name().clone());
                c_taxs = rec_f(c_taxs, Rc::clone(elem));
                taxs = taxs.add_child(c_taxs);
            }
            taxs
        }
        taxonomy = rec_f(taxonomy, g);
        taxonomy
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn taxonomy_from_group_works() {
        let g = Rc::new(Group::root());
        let t = Taxonomy::from(g.clone());
        assert_eq!(t, Taxonomy::new(g.name().clone()));

        let g = Rc::new(Group::root());
        let g_1 = Rc::new(Group::new("第一层第一个"));
        g.add_group(g_1);
        let t = Taxonomy::from(g.clone());
        assert_eq!(
            t,
            Taxonomy::new(g.name().clone()).add_child(Taxonomy::new("第一层第一个".to_string()))
        );

        let g = Rc::new(Group::root());
        let g_1 = Rc::new(Group::new("第一层第一个"));
        let g_2 = Rc::new(Group::new("第一层第二个"));
        g.add_group(g_1);
        g.add_group(g_2);
        let t = Taxonomy::from(g.clone());
        assert_eq!(
            t,
            Taxonomy::new(g.name().clone())
                .add_child(Taxonomy::new("第一层第一个".to_string()))
                .add_child(Taxonomy::new("第一层第二个".to_string()))
        );

        let g = Rc::new(Group::root());
        let g_1 = Rc::new(Group::new("第一层第一个"));
        let g_2 = Rc::new(Group::new("第一层第二个"));
        let g_2_1 = Rc::new(Group::new("第二层第一个"));
        g_2.add_group(g_2_1);
        g.add_group(g_1);
        g.add_group(g_2);
        println!("group: {:?}", g);
        let t = Taxonomy::from(g.clone());
        assert_eq!(
            t,
            Taxonomy::new(g.name().clone())
                .add_child(Taxonomy::new("第一层第一个".to_string()))
                .add_child(
                    Taxonomy::new("第一层第二个".to_string())
                        .add_child(Taxonomy::new("第二层第一个".to_string()))
                )
        );
    }
}
